<?php
/*
 * @Author: 李志刚
 * @CopyRight: 2020-2030 衡水山木枝技术服务有限公司
 * @Date: 2021-06-29 10:40:39
 * @Description: 封装拼多多请求方法
 * @LastEditors: 李志刚
 * @LastEditTime: 2021-06-30 17:53:52
 * @FilePath: /qingshanERP/app/Customize/PddRequest.php
 */

namespace App\Customize;

use App\Models\QingShanERP\Shop;
use Illuminate\Support\Facades\Redis;

class PddRequest
{
    // 取拼多多的token，同时判断是不是有效期内的
    public static function getToken($shopid){
        $hav = Redis::exists('shop-token:' . $shopid);
        // 没有的话查下是不是数据库的还没有过期
        if (!$hav) {
            $shop = Shop::findOrFail($shopid);
            if ($shop->expires_at < time() || is_null($shop->access_token)) {
                $token = '';
            }else{
                $token = $shop->access_token;
                Redis::setex('shop-token:' . $shopid, $shop->expires_at - time(), $shop->access_token);
            }
        }else{
            $token = Redis::get('shop-token:' . $shopid);
        }
        return $token;
    }
    /**
     * 发起请求
     * @param string $method , 请求的接口地址
     * @param array  $params , 请求参数
     * @param string $data_type 返回的数据格式
     *
     * @return mixed
     */
    public static function request($method, $params = [], $data_type = 'JSON')
    {
        $self = new self();
        $config = config('pdd');
        $params = $self->paramsHandle($params);
        $params['type'] = $method;
        $params['client_id'] = $config['client_id'];
        $params['timestamp'] = strval(time());
        $params['data_type'] = $data_type;
        $params['sign_method'] = 'md5';
        $params['version'] = 'V1';
        $params['sign'] = $self->signature($params);
        $url = $config['api_url'];
        $res = $self->postCurl($url, $params);
        return $res;
    }
    // 请求接口用的CURL功能，http_build_query了一下body，这里比较坑
    public function postCurl($url, $body, $type = "POST", $json = 0)
    {
        $header = array();
        //1.创建一个curl资源
        $ch = curl_init();
        //2.设置URL和相应的选项
        curl_setopt($ch, CURLOPT_URL, $url); //设置url
        //1)设置请求头
        if ($json) {
            array_push($header, 'Content-Type:application/json');
        } else {
            array_push($header, 'Content-Type:application/x-www-form-urlencoded;charset=utf-8');
        }
        //设置请求头
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        //设置为false,只会获得响应的正文(true的话会连响应头一并获取到)
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5); // 设置超时限制防止死循环
        //设置发起连接前的等待时间，如果设置为0，则无限等待。
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
        //将curl_exec()获取的信息以文件流的形式返回，而不是直接输出。
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        //上传文件相关设置
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 对认证证书来源的检查
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // 从证书中检查SSL加密算

        //3)设置提交方式
        switch ($type) {
            case "GET":
                curl_setopt($ch, CURLOPT_HTTPGET, true);
                break;
            case "POST":
                curl_setopt($ch, CURLOPT_POST, true);
                break;
            case "PUT": //使用一个自定义的请求信息来代替"GET"或"HEAD"作为HTTP请 求。这对于执行"DELETE" 或者其他更隐蔽的HTT
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
                break;
            case "DELETE":
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
                break;
        }

        //2)设备请求体
        if (count($body) > 0 && $type == 'POST') {
            // $body = $json ? json_encode($body) : $body;
            $postFields = http_build_query($body);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields); //全部数据使用HTTP协议中的"POST"操作来发送。
        }

        //3.抓取URL并把它传递给浏览器
        $res = curl_exec($ch);
        $result = json_decode($res, true);
        //4.关闭curl资源，并且释放系统资源
        curl_close($ch);
        if (empty($result)) {
            return $res;
        } else {
            return $result;
        }
    }

    /**
     * 参数排序
     * @param array $params
     *
     * @return array
     */
    protected function paramsHandle(array $params)
    {
        array_walk($params, function (&$item) {
            if (is_array($item)) {
                $item = json_encode($item);
            }
            if (is_bool($item)) {
                $item = ['false', 'true'][intval($item)];
            }
        });

        return $params;
    }

    /**
     * 签名
     * @param $params
     *
     * @return string
     */
    private function signature($params)
    {
        ksort($params);
        $paramsStr = '';
        array_walk($params, function ($item, $key) use (&$paramsStr) {
            if ('@' != substr($item, 0, 1)) {
                $paramsStr .= sprintf('%s%s', $key, $item);
            }
        });
        $client_secret = config('pdd')['client_secret'];
        return strtoupper(md5(sprintf('%s%s%s', $client_secret, $paramsStr, $client_secret)));
    }
}
